package com.bosssoft.login.utils;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author diana
 * @create 2021-02-08 20:20
 */
@Slf4j
public class JwtUtil {

    private static final long EXPIRE = 1000 * 60 * 60 * 24;

    private static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";

    public static String createJwtToken(String id, String username){
        String jwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("user")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                .claim("id", id)
                .claim("username", username)
                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();
        return jwtToken;
    }

    public static String createJwtToken(String id, String username, long expire){
        String jwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("user")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .claim("id", id)
                .claim("username", username)
                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();
        return jwtToken;
    }

    /**
     * 判断token是否存在与有效
     * @param jwtToken
     * @return
     */
    public static boolean checkToken(String jwtToken) {
        if(StringUtils.isEmpty(jwtToken)) {
            return false;
        }
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (ExpiredJwtException e) {
            log.error("Token 已过期");
            throw new SecurityException();
        } catch (UnsupportedJwtException e) {
            log.error("不支持的 Token");
            throw new SecurityException();
        } catch (MalformedJwtException e) {
            log.error("Token 无效");
            throw new SecurityException();
        } catch (SignatureException e) {
            log.error("无效的 Token 签名");
            throw new SecurityException();
        } catch (IllegalArgumentException e) {
            log.error("Token 参数不存在");
            throw new SecurityException();
        }
        return true;
    }

    /**
     * 判断token是否存在与有效
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) {
                return false;
            }
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据token获取用户id
     * @param token
     * @return
     */
    public static String getUserIdByJwtToken(String token) {
        Claims claims = parse(token);
        return (String)claims.get("id");
    }

    /**
     * 根据token获取用户名
     * @param token
     * @return
     */
    public static String getUserNameByJwtToken(String token) {
        Claims claims = parse(token);
        return (String)claims.get("username");
    }

    private static Claims parse(String token) {
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token);
            return claimsJws.getBody();
        } catch (ExpiredJwtException e) {
            log.error("Token 已过期");
            throw new SecurityException();
        } catch (UnsupportedJwtException e) {
            log.error("不支持的 Token");
            throw new SecurityException();
        } catch (MalformedJwtException e) {
            log.error("Token 无效");
            throw new SecurityException();
        } catch (SignatureException e) {
            log.error("无效的 Token 签名");
            throw new SecurityException();
        } catch (IllegalArgumentException e) {
            log.error("Token 参数不存在");
            throw new SecurityException();
        }
    }

    public static Date getExpiration(String token) {
        return parse(token).getExpiration();
    }
}
